package com.yzy.jvm;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;

import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author yzy
 * @date 2020/4/28 
 * @description
 */
public class ApiResult<T> {

	private Integer resultCode = 0;

	private String errorMsg = "";

	private T data;

	public Integer getResultCode() {
		return resultCode;
	}

	public void setResultCode(Integer resultCode) {
		this.resultCode = resultCode;
	}

	public String getErrorMsg() {
		return errorMsg;
	}

	public void setErrorMsg(String errorMsg) {
		this.errorMsg = errorMsg;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	public static final String RESULT_CODE = "resultCode";
	public static final String DATA = "data";
	public static final String ERROR_MSG = "errorMsg";

	public ApiResult() {}

	public ApiResult(Integer resultCode, String errorMsg, T data) {
		this.resultCode = resultCode;
		this.errorMsg = errorMsg;
		this.data = data;
	}

	public boolean isSuccess() {
		return null != this.getResultCode() && 0 == this.getResultCode();
	}

	public String toJSONString() {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put(RESULT_CODE, resultCode);
		jsonObject.put(DATA, data);
		jsonObject.put(ERROR_MSG, errorMsg);
		return jsonObject.toJSONString();
	}

	public static ApiResult fromJSON(String json) {
		try {
			return JSONObject.parseObject(json, ApiResult.class);
		}catch (Exception e) {
			e.printStackTrace();
			ApiResult apiResult = new ApiResult();
			apiResult.setResultCode(-1);
			return apiResult;
		}
	}

	/**
	 * 复用 ParameterizedTypeImpl 对象，防止频繁创建导致内存溢出
	 */
	private static ConcurrentMap<String, Type> classTypeCache = new ConcurrentHashMap<>(16, 0.75f, 1);

	public static <T> ApiResult<T> fromJSON(String json, Type dataType, Type... actualTypeArguments) {
		try {
			if(actualTypeArguments != null && actualTypeArguments.length > 0){
				String typeKey = dataType.getTypeName() + actualTypeArguments[0].getTypeName();
				Type cachedType = classTypeCache.get(typeKey);
				if (cachedType == null) {
					cachedType = new ParameterizedTypeImpl(new Type[]{new ParameterizedTypeImpl(actualTypeArguments, null, dataType)}, null, ApiResult.class );
					classTypeCache.putIfAbsent(typeKey, cachedType);
				}
				return JSONObject.parseObject(json, cachedType);
			}
			if (dataType instanceof ParameterizedTypeImpl) {
				return JSONObject.parseObject(json, dataType);
			}
			return JSONObject.parseObject(json, new TypeReference<ApiResult<T>>(dataType) {});
		}catch (Exception e) {
			e.printStackTrace();
			ApiResult apiResult = new ApiResult();
			apiResult.setResultCode(-1);
			return apiResult;
		}

	}
/*
	// test
	public static void main(String[] args) {

		int i = 0;
		Date date = new Date();
		while (true) {
			List<PayMemberTypeRespDTO> list1 = getPayMemberType();
			Member member = getMember();
			if (i++ % 10000 ==0) {
				long s = date.getTime();
				date = new Date();
				System.out.println(date.getTime() - s);
			}
		}
	}

	// test
	private static Member getMember() {

		String json = "{\"data\":{\"ageGroup\":1,\"basicMemberStatus\":\"N\",\"belongBrand\":\"P\",\"birthdate\":\"0327\",\"birthday\":\"1995-03-27 00:00:00\",\"certified\":0,\"channelValue\":\"750120\",\"familySize\":4,\"firstConsumeStore\":\"750048\",\"identifyCode\":1,\"identity\":\"18738192271\",\"incoming\":0,\"inviteLimit\":20,\"job\":\"\",\"lastTime\":\"2020-05-04 11:18:06\",\"levelId\":2,\"memberId\":122490630,\"memberNum\":1000100012249063010,\"memberStatus\":\"N\",\"memberType\":\"P\",\"merchant\":1,\"nickName\":\"Iris\",\"payMemberEndTime\":\"2021-05-04 23:59:59\",\"payMemberStartTime\":\"2020-05-04 11:03:06\",\"realName\":\"\",\"registerChannel\":\"10012\",\"registerDate\":\"2018-06-07 06:26:20\",\"sex\":\"F\"},\"resultCode\":0,\"errorMsg\":\"\"}";
		//String json = "{\"resultCode\":0,\"errorMsg\":\"\"}";
		com.pagoda.member.common.transfer.vo.ApiResult<MemberCompleteSearchSingleRespDTO> apiResult = com.pagoda.member.common.transfer.vo.ApiResult.fromJSON(json, MemberCompleteSearchSingleRespDTO.class);

		MemberCompleteSearchSingleRespDTO data = apiResult.getData();
		Member member = TransferUtil.convertToMember(data);
		//data = null;
		//apiResult = null;
		//member = null;
		return member;
	}

	// test
	private static List<PayMemberTypeRespDTO> getPayMemberType() {

		String json = "{\"data\":{\"content\":[{\"automaticRenew\":0,\"differenceRefund\":0,\"inviteCount\":0,\"payMemberIdentifyCode\":2,\"payMemberPeriodCode\":2,\"payMemberTypeCode\":1,\"payMemberTypeName\":\"试用心享会员\",\"price\":0,\"shelvesStatus\":\"U\"},{\"automaticRenew\":0,\"differenceRefund\":1,\"inviteCount\":20,\"inviteType\":1,\"payMemberIdentifyCode\":1,\"payMemberPeriodCode\":4,\"payMemberTypeCode\":2,\"payMemberTypeName\":\"心享会员年卡\",\"price\":19900,\"shelvesStatus\":\"U\"},{\"automaticRenew\":0,\"differenceRefund\":0,\"inviteCount\":0,\"payMemberIdentifyCode\":1,\"payMemberPeriodCode\":3,\"payMemberTypeCode\":3,\"payMemberTypeName\":\"心享会员季卡\",\"price\":6500,\"shelvesStatus\":\"U\"},{\"automaticRenew\":1,\"differenceRefund\":1,\"inviteCount\":20,\"inviteType\":1,\"payMemberIdentifyCode\":1,\"payMemberPeriodCode\":4,\"payMemberTypeCode\":4,\"payMemberTypeName\":\"心享会员续费年卡\",\"price\":19900,\"shelvesStatus\":\"U\"},{\"automaticRenew\":1,\"differenceRefund\":0,\"inviteCount\":0,\"payMemberIdentifyCode\":1,\"payMemberPeriodCode\":3,\"payMemberTypeCode\":5,\"payMemberTypeName\":\"心享会员续费季卡\",\"price\":6500,\"shelvesStatus\":\"U\"}],\"empty\":false,\"first\":true,\"last\":true,\"number\":0,\"numberOfElements\":5,\"pageable\":{\"offset\":0,\"pageNumber\":0,\"pageSize\":200},\"size\":200,\"total\":5,\"totalElements\":5,\"totalPages\":1},\"resultCode\":0,\"errorMsg\":\"\"}";
		com.pagoda.member.common.transfer.vo.ApiResult<PageResult<PayMemberTypeRespDTO>> apiResult = com.pagoda.member.common.transfer.vo.ApiResult.fromJSON(json, PageResult.class, PayMemberTypeRespDTO.class);
		return apiResult.getData().getContent();
	}*/

}
